import threading
from typing import Dict, List, Optional, Callable
from dataclasses import dataclass
from enum import Enum, auto

class TaskStatus(Enum):
    """任务状态枚举"""
    QUEUED = auto()
    DOWNLOADING = auto()
    COMPLETED = auto()
    FAILED = auto()
    CANCELLED = auto()
    PAUSED = auto()

@dataclass
class TaskInfo:
    """任务信息类"""
    id: int
    url: str
    format_id: str
    title: str
    thumbnail: str
    status: TaskStatus
    progress: float
    format_note: str
    resolution: str
    ext: str
    message: Optional[str] = None

class TaskManager:
    """任务管理器"""
    def __init__(self, max_concurrent: int = 3):
        self.max_concurrent = max_concurrent
        self.tasks: Dict[int, TaskInfo] = {}
        self.queue: List[int] = []
        self.active: Dict[int, threading.Thread] = {}
        self.next_id = 1
        self.lock = threading.Lock()
        
        # 回调函数
        self.on_task_added: Optional[Callable[[TaskInfo], None]] = None
        self.on_task_updated: Optional[Callable[[TaskInfo], None]] = None
        self.on_task_removed: Optional[Callable[[int], None]] = None
    
    def add_task(self, task_info: dict) -> int:
        """添加任务"""
        with self.lock:
            task_id = self.next_id
            self.next_id += 1
            
            task = TaskInfo(
                id=task_id,
                url=task_info["url"],
                format_id=task_info["format_id"],
                title=task_info["title"],
                thumbnail=task_info["thumbnail"],
                status=TaskStatus.QUEUED,
                progress=0.0,
                format_note=task_info["format_note"],
                resolution=task_info["resolution"],
                ext=task_info["ext"]
            )
            
            self.tasks[task_id] = task
            self.queue.append(task_id)
            
            if self.on_task_added:
                self.on_task_added(task)
            
            return task_id
    
    def update_task(self, task_id: int, **kwargs) -> None:
        """更新任务信息"""
        with self.lock:
            if task_id in self.tasks:
                task = self.tasks[task_id]
                for key, value in kwargs.items():
                    setattr(task, key, value)
                
                if self.on_task_updated:
                    self.on_task_updated(task)
    
    def remove_task(self, task_id: int) -> None:
        """移除任务"""
        with self.lock:
            if task_id in self.tasks:
                del self.tasks[task_id]
                if task_id in self.queue:
                    self.queue.remove(task_id)
                if task_id in self.active:
                    del self.active[task_id]
                
                if self.on_task_removed:
                    self.on_task_removed(task_id)
    
    def toggle_task(self, task_id: int) -> None:
        """切换任务状态（暂停/恢复）"""
        with self.lock:
            if task_id not in self.tasks:
                return
            
            task = self.tasks[task_id]
            
            if task.status == TaskStatus.PAUSED:
                # 恢复下载
                if task_id not in self.queue:
                    self.queue.append(task_id)
                task.status = TaskStatus.QUEUED
                if self.on_task_updated:
                    self.on_task_updated(task)
            
            elif task.status in [TaskStatus.QUEUED, TaskStatus.DOWNLOADING]:
                # 暂停下载
                if task_id in self.queue:
                    self.queue.remove(task_id)
                task.status = TaskStatus.PAUSED
                if self.on_task_updated:
                    self.on_task_updated(task)
    
    def cancel_task(self, task_id: int) -> None:
        """取消任务"""
        with self.lock:
            if task_id not in self.tasks:
                return
            
            task = self.tasks[task_id]
            
            if task_id in self.queue:
                self.queue.remove(task_id)
            
            task.status = TaskStatus.CANCELLED
            if self.on_task_updated:
                self.on_task_updated(task)
    
    def start_task(self, task_id: int, download_func: Callable) -> None:
        """启动任务"""
        with self.lock:
            if task_id not in self.tasks:
                return
            
            task = self.tasks[task_id]
            task.status = TaskStatus.DOWNLOADING
            
            if self.on_task_updated:
                self.on_task_updated(task)
            
            thread = threading.Thread(
                target=download_func,
                args=(task_id,),
                daemon=True
            )
            thread.start()
            
            self.active[task_id] = thread
    
    def finish_task(self, task_id: int, success: bool, message: Optional[str] = None) -> None:
        """完成任务"""
        with self.lock:
            if task_id not in self.tasks:
                return
            
            task = self.tasks[task_id]
            task.status = TaskStatus.COMPLETED if success else TaskStatus.FAILED
            if message:
                task.message = message
            
            if task_id in self.active:
                del self.active[task_id]
            
            if self.on_task_updated:
                self.on_task_updated(task)
    
    def update_progress(self, task_id: int, progress: float) -> None:
        """更新任务进度"""
        with self.lock:
            if task_id in self.tasks:
                task = self.tasks[task_id]
                task.progress = progress
                
                if self.on_task_updated:
                    self.on_task_updated(task)
    
    def process_queue(self) -> None:
        """处理任务队列"""
        with self.lock:
            # 检查是否有空闲槽位
            if len(self.active) >= self.max_concurrent:
                return
            
            # 检查是否有等待的任务
            if not self.queue:
                return
            
            # 获取下一个任务
            task_id = self.queue[0]
            self.queue.pop(0)
            
            # 更新任务状态
            task = self.tasks[task_id]
            task.status = TaskStatus.DOWNLOADING
            
            if self.on_task_updated:
                self.on_task_updated(task)
            
            return task_id 